fix(assets-controller): heal native token assetsInfo entries#9099
Conversation
… metadata This commit introduces a new test case to ensure that the middleware correctly refetches asset metadata when the stored type is stale, even if an image is present. The test verifies that a previously misclassified native asset is updated to its correct type, enhancing the robustness of the asset handling logic.
|
@cursor READ AND FOLLOW THESE MEMORY FILES: /babysit fix CI |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7480667. Configure here.
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
| const assetsInfoAssetIdsSet = new Set( | ||
| Object.keys(normalizedResponse.assetsInfo ?? {}) as Caip19AssetId[], | ||
| ); |
There was a problem hiding this comment.
@cursor I had a good back and forth with Claude around this.
The reason this works is because RPC detection can pick this up and therefore have some assetsInfo to rely on.
So as a safe measure we can use both the assetsInfo and assetsBalance.
const assetsInfoAssetIdsSet = new Set([
...Object.keys(normalizedResponse.assetsInfo ?? {}),
...Object.entries(normalizedResponse.assetsBalance ?? {}).flatMap(
([_, b]) => Object.keys(b),
),
] as Caip19AssetId[]);
Thoughts?
There was a problem hiding this comment.
Good call — I agree with your proposal, and I’ve already applied it.
Thoughts
Using both normalized assetsInfo and normalized assetsBalance keys is the safer behavior:
- It preserves the
assetsInfo-first logic. - It also heals stale types when a response only touches balance (which can happen via RPC detection flows).
- Because both come from
normalizedResponse, it avoids the non-checksummed key mismatch bug.
What I changed
Implemented reconciliation key set as union of:
Object.keys(normalizedResponse.assetsInfo ?? {})- asset IDs found in
normalizedResponse.assetsBalanceentries
Then reconciles metadata[assetId].type for all those touched IDs.
Added coverage
- New test:
reconciles a stale native type stored as erc20 when assetsBalance includes the asset - Existing normalized-key reconciliation test remains in place.
Changelog
Updated to reflect behavior now applies when asset appears in incoming:
assetsInfoorassetsBalance.
Validation run
Passed locally:
yarn lint:misc:checkyarn eslint packages/assets-controller/src/AssetsController.ts packages/assets-controller/src/AssetsController.test.tsyarn workspace @metamask/assets-controller run jest --no-coverage src/AssetsController.test.ts --runInBand --forceExityarn changelog:validate
Git
- Commit:
0eef15d37 - Pushed to
fix/heal-native-token-entries - PR fix(assets-controller): heal native token assetsInfo entries #9099 updated
- Fresh CI run is in progress for this commit.
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
…healing metadata cp-13.35.0 (#43477) ## **Description** Patch for this core fix: MetaMask/core#9099 ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: fix(assets-controller): update patch to add reconciliation/self-healing metadata ## **Related issues** Fixes: #43352 ## **Manual testing steps** 1. Start application on 13.34.0. Add IMX chain and token. 2. Inspect state - `AssetsController.assetsInfo["eip155:13371/erc20:0x0000000000000000000000000000000000000000"]` - See that the token is marked as "erc20" 3. Start application with these changes 4. Inspect state - `AssetsController.assetsInfo["eip155:13371/erc20:0x0000000000000000000000000000000000000000"]` - See that the token is marked as "native" ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ```json { "aggregators": [], "decimals": 18, "erc20Permit": false, "image": "https://static.cx.metamask.io/api/v2/tokenIcons/assets/eip155/13371/erc20/0x0000000000000000000000000000000000000000.png", "name": "Immutable X", "occurrences": 100, "symbol": "IMX", "type": "erc20" } ``` ### **After** ``` { "aggregators": [], "decimals": 18, "erc20Permit": false, "image": "https://static.cx.metamask.io/api/v2/tokenIcons/assets/eip155/13371/erc20/0x0000000000000000000000000000000000000000.png", "name": "Immutable X", "occurrences": 100, "symbol": "IMX", "type": "native" } ``` https://www.loom.com/share/45f25216181146a69fc4730786c8fec9 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how persisted asset metadata types are updated across websocket/RPC flows; incorrect classification could affect portfolio display until the next reconcile, but the logic is narrowly corrective. > > **Overview** > Updates the **Yarn patch** for `@metamask/assets-controller@8.3.2` to backport MetaMask/core#9099: asset metadata **types** are reconciled when balance/info updates land, so mislabeled entries (e.g. IMX native at the zero address stored as `erc20`) are corrected to `native`, `spl`, or `erc20`. > > The patch adds a **`getAssetType`** helper on `AssetsController` and passes it into **BackendWebsocket**, **RPC**, and **price** data sources (replacing the websocket’s `isNativeAsset` hook). During `_updateState`, it walks asset IDs from incoming `assetsInfo` / `assetsBalance` and **self-heals** `metadata[assetId].type` when it disagrees with `getAssetType`, marking those IDs as changed metadata. > > `yarn.lock` is refreshed for the new patch hash/checksum only. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 13e0626. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…healing metadata cp-13.35.0 (#43477) ## **Description** Patch for this core fix: MetaMask/core#9099 ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: fix(assets-controller): update patch to add reconciliation/self-healing metadata ## **Related issues** Fixes: #43352 ## **Manual testing steps** 1. Start application on 13.34.0. Add IMX chain and token. 2. Inspect state - `AssetsController.assetsInfo["eip155:13371/erc20:0x0000000000000000000000000000000000000000"]` - See that the token is marked as "erc20" 3. Start application with these changes 4. Inspect state - `AssetsController.assetsInfo["eip155:13371/erc20:0x0000000000000000000000000000000000000000"]` - See that the token is marked as "native" ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ```json { "aggregators": [], "decimals": 18, "erc20Permit": false, "image": "https://static.cx.metamask.io/api/v2/tokenIcons/assets/eip155/13371/erc20/0x0000000000000000000000000000000000000000.png", "name": "Immutable X", "occurrences": 100, "symbol": "IMX", "type": "erc20" } ``` ### **After** ``` { "aggregators": [], "decimals": 18, "erc20Permit": false, "image": "https://static.cx.metamask.io/api/v2/tokenIcons/assets/eip155/13371/erc20/0x0000000000000000000000000000000000000000.png", "name": "Immutable X", "occurrences": 100, "symbol": "IMX", "type": "native" } ``` https://www.loom.com/share/45f25216181146a69fc4730786c8fec9 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how persisted asset metadata types are updated across websocket/RPC flows; incorrect classification could affect portfolio display until the next reconcile, but the logic is narrowly corrective. > > **Overview** > Updates the **Yarn patch** for `@metamask/assets-controller@8.3.2` to backport MetaMask/core#9099: asset metadata **types** are reconciled when balance/info updates land, so mislabeled entries (e.g. IMX native at the zero address stored as `erc20`) are corrected to `native`, `spl`, or `erc20`. > > The patch adds a **`getAssetType`** helper on `AssetsController` and passes it into **BackendWebsocket**, **RPC**, and **price** data sources (replacing the websocket’s `isNativeAsset` hook). During `_updateState`, it walks asset IDs from incoming `assetsInfo` / `assetsBalance` and **self-heals** `metadata[assetId].type` when it disagrees with `getAssetType`, marking those IDs as changed metadata. > > `yarn.lock` is refreshed for the new patch hash/checksum only. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 13e0626. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…add reconciliation/self-healing metadata cp-13.35.0 (#43477) ## **Description** Patch for this core fix: MetaMask/core#9099 ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: fix(assets-controller): update patch to add reconciliation/self-healing metadata ## **Related issues** Fixes: #43352 ## **Manual testing steps** 1. Start application on 13.34.0. Add IMX chain and token. 2. Inspect state - `AssetsController.assetsInfo["eip155:13371/erc20:0x0000000000000000000000000000000000000000"]` - See that the token is marked as "erc20" 3. Start application with these changes 4. Inspect state - `AssetsController.assetsInfo["eip155:13371/erc20:0x0000000000000000000000000000000000000000"]` - See that the token is marked as "native" ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ```json { "aggregators": [], "decimals": 18, "erc20Permit": false, "image": "https://static.cx.metamask.io/api/v2/tokenIcons/assets/eip155/13371/erc20/0x0000000000000000000000000000000000000000.png", "name": "Immutable X", "occurrences": 100, "symbol": "IMX", "type": "erc20" } ``` ### **After** ``` { "aggregators": [], "decimals": 18, "erc20Permit": false, "image": "https://static.cx.metamask.io/api/v2/tokenIcons/assets/eip155/13371/erc20/0x0000000000000000000000000000000000000000.png", "name": "Immutable X", "occurrences": 100, "symbol": "IMX", "type": "native" } ``` https://www.loom.com/share/45f25216181146a69fc4730786c8fec9 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how persisted asset metadata types are updated across websocket/RPC flows; incorrect classification could affect portfolio display until the next reconcile, but the logic is narrowly corrective. > > **Overview** > Updates the **Yarn patch** for `@metamask/assets-controller@8.3.2` to backport MetaMask/core#9099: asset metadata **types** are reconciled when balance/info updates land, so mislabeled entries (e.g. IMX native at the zero address stored as `erc20`) are corrected to `native`, `spl`, or `erc20`. > > The patch adds a **`getAssetType`** helper on `AssetsController` and passes it into **BackendWebsocket**, **RPC**, and **price** data sources (replacing the websocket’s `isNativeAsset` hook). During `_updateState`, it walks asset IDs from incoming `assetsInfo` / `assetsBalance` and **self-heals** `metadata[assetId].type` when it disagrees with `getAssetType`, marking those IDs as changed metadata. > > `yarn.lock` is refreshed for the new patch hash/checksum only. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 13e0626. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->



Explanation
This commit introduces a new test case to ensure that the middleware correctly refetches asset metadata when the stored type is stale, even if an image is present. The test verifies that a previously misclassified native asset is updated to its correct type, enhancing the robustness of the asset handling logic.
References
Checklist
Note
Low Risk
Localized metadata correction on merge using existing type resolution; only touches assets in the incoming update and is covered by new tests.
Overview
AssetsControllernow self-heals staleassetsInfo.typevalues when applying pipeline updates. After merging incoming metadata, it walks asset IDs present in the currentassetsInfoorassetsBalancepayload, compares each entry’stypeto#getAssetType(assetId), and rewrites mismatches (e.g. zero-address “native” tokens still labelederc20from older persisted state).Healing runs on
handleAssetsUpdate/#updateStatepaths, so a balance-only or metadata refresh can fix types without a separate migration. Genuine ERC-20s are left unchanged; normalization still applies so non-checksummed keys in responses reconcile against the canonical ID.The changelog records the fix under Unreleased; tests cover native→
erc20healing viaassetsInfoandassetsBalance, no-op for real ERC-20s, and checksum vs lowercase asset IDs.Reviewed by Cursor Bugbot for commit 249ad86. Bugbot is set up for automated code reviews on this repo. Configure here.